#!/usr/bin/env python
# -*- coding:utf-8 -*-

from controller.ssoUserController import SsoUserController

from models import db
from service.userTokenService import UserTokenService
from service.verifyMailService import VerifyMailService
from utils import commons
from utils.loggings import loggings
from utils.response_code import RET, error_map_EN
from utils.rsa_encryption_decryption import RSAEncryptionDecryption


class SsoUserService(SsoUserController):

    # 注册
    @classmethod
    def register(cls, **kwargs):
        try:
            # ssoUser 用户单点登录表注册
            from controller.ssoUserController import SsoUserController
            if SsoUserController.get(account=kwargs.get('account'))['totalCount'] != 0:
                return {'code': RET.DATAERR, 'message': '账号名存在', "data": "账号名存在"}

            sso_user_info = SsoUserController.add(**kwargs)
            if sso_user_info['code'] != RET.OK:
                return {'code': RET.DATAERR, 'message': error_map_EN[RET.DATAERR], "data": "注册错误"}

            return {'code': RET.OK, 'message': error_map_EN[RET.OK], "data": sso_user_info['data']}
        except Exception as e:
            loggings.exception(1, e)
            return {'code': RET.LOGINERR, 'message': error_map_EN[RET.LOGINERR],
                    'data': {'error': f"注册失败：{e}"}}

    # 登录
    @classmethod
    def login(cls, **kwargs):
        # 接收参数
        user_account = kwargs.get('account')
        user_password = kwargs.get('password')

        try:
            # 校验验证码
            from service.verifyCodeService import VerifyCodeService
            check_verify_code = VerifyCodeService.check_verify_code(kwargs.get('verify_code_id'),
                                                                    kwargs.get('verify_code'))

            if check_verify_code['code'] != RET.OK:
                return {'code': check_verify_code['code'], 'message': check_verify_code['message'],
                        'data': {'error': check_verify_code['error']}}
        except Exception as e:
            loggings.exception(1, e)
            return {'code': RET.LOGINERR, 'message': "数据库连接异常，验证码查验失败",
                    'data': {'error': "数据库连接异常，验证码查验失败"}}

        # 校验账号密码
        filter_list = [cls.account == user_account, cls.is_deleted == 0]
        try:
            user_info = db.session.query(cls.user_id, cls.account, cls.password, cls.valid_type, cls.user_type,
                                         cls.status). \
                filter(*filter_list).first()
        except Exception as e:
            loggings.exception(1, e)
            return {'code': RET.LOGINERR, 'message': "数据库连接异常，登录失败",
                    'data': {'error': "数据库连接异常，登录失败"}}

        error_info = "账号或者密码错误"

        # 验证用户是否存在
        if not user_info:
            return {'code': RET.NODATA, 'message': error_info, 'data': {'error': error_info}}

        user_info_data = commons.query_to_dict(user_info)
        user_type = user_info_data.get('user_type')

        # 校验密码
        try:
            if RSAEncryptionDecryption.decrypt(
                    user_info_data.get('password')) != RSAEncryptionDecryption.timestamp_decrypt(user_password):
                return {'code': RET.LOGINERR, 'message': error_info, 'data': {'error': error_info}}
        except Exception as e:
            loggings.exception(1, e)
            return {'code': RET.LOGINERR, 'message': "数据库连接异常，密码查验失败",
                    'data': {'error': "数据库连接异常，密码查验失败"}}

        # 校验用户状态 status 0- 有效 1- 冻结
        if user_info_data.get('status') == 1:
            return {'code': RET.LOGINERR, 'message': "您的账号被冻结，请联系管理员",
                    'data': {'error': "您的账号被冻结，请联系管理员"}}

        user_id = user_info_data.get('user_id')
        login_type = user_info_data.get('login_type')
        user_name = user_info_data.get('user_name', 'user')

        # 生成token
        from .userTokenService import UserTokenService
        token = UserTokenService.create_token(user_id, user_name, user_type)

        # 自定义接口返回的信息准备
        back_data = {
            'user_id': user_id,
            'user_name': user_name,
            'login_type': login_type,
            'role_type': user_type,
            'token': token
        }
        return {'code': RET.OK, 'message': error_map_EN[RET.OK], "data": back_data}

    # 登出
    @classmethod
    def logout(cls):
        back_data = {}
        from flask import g
        if g.user:
            back_data['user_id'] = g.user.pop('user_id')
            back_data['user_type'] = g.user.pop('user_type')
        else:
            return {'code': RET.NODATA, 'message': error_map_EN[RET.NODATA], 'data': {'error': '用户未登录'}}
        return {'code': RET.OK, 'message': error_map_EN[RET.OK], "data": back_data}

    # 发送邮箱验证码
    @classmethod
    def verify_email(cls, **kwargs):
        target_email = kwargs.get('target_email')
        from service.verifyMailService import VerifyMailService
        res = VerifyMailService.send(target_email)
        return res

    # 邮箱验证码验证
    @classmethod
    def email_code_check(cls, **kwargs):
        mail_verify_id = kwargs.get('mail_verify_id')
        mail_verify_code = kwargs.get('mail_verify_code')
        email = kwargs.get('email')
        return VerifyMailService.check_verify_code(mail_verify_id, mail_verify_code, email)

    # 用户修改密码
    @classmethod
    def change_password(cls, **kwargs):
        user_info = cls.get(user_id=kwargs.get('user_id'))
        if user_info['totalCount'] == 0:
            return {'code': RET.DATAERR, 'message': '用户信息不存在！', "data": {'error': '用户信息不存在！'}}

        password = RSAEncryptionDecryption.decrypt(user_info['data'][0].get('password'))
        if password != kwargs.get('old_password'):
            return {'code': RET.DATAERR, 'message': '密码错误！', "data": {'error': '密码错误！'}}

        try:

            res = SsoUserController.update(
                user_id=kwargs.get('user_id'),
                password=kwargs.get('new_password')
            )
            return res

        except Exception as e:
            loggings.exception(1, e)
            return {'code': RET.DBERR, 'message': error_map_EN[RET.DBERR], 'data': {'error': str(e)}}

    # 根据用户名向邮箱发送验证码
    @classmethod
    def forget_password_send(cls, **kwargs):
        user_info = cls.get(account=kwargs.get('account'), status=1)
        if user_info['totalCount'] == 0:
            return {'code': RET.DATAERR, 'message': '用户信息不存在！', "data": {'error': '用户信息不存在！'}}

        return cls.verify_email(target_email=user_info['data'][0].get('email'))

    @classmethod
    def forget_password_recover(cls, **kwargs):
        user_info = cls.get(account=kwargs.get('account'), status=1)
        if user_info['totalCount'] == 0:
            return {'code': RET.DATAERR, 'message': '用户信息不存在！', "data": {'error': '用户信息不存在！'}}

        res_email_check = cls.email_code_check(**kwargs)
        if res_email_check['code'] != RET.OK:
            return res_email_check

        return {'code': RET.OK, 'message': error_map_EN[RET.OK],
                "data": {'password': RSAEncryptionDecryption.decrypt(user_info['data'][0].get('password'))}}

    # 微信绑定
    @classmethod
    def weixin_register(cls, **kwargs):
        user_id = kwargs.get('user_id')
        open_id = kwargs.get('openid')
        head_imgurl = kwargs.get('headimgurl')

        # 检查是否绑定
        try:
            user_info = db.session.query(cls).filter(cls.open_id == open_id).filter(cls.is_deleted == 0)

        except Exception as e:
            loggings.exception(1, e)
            return {'code': RET.DBERR, 'message': '数据库异常，获取信息失败', 'error': str(e)}

        if user_info.first():
            return {'code': RET.NODATA, 'message': '该微信已经绑定', 'error': '该微信已经绑定'}

        # 查找用户
        try:
            user_info = db.session.query(cls).filter(cls.user_id == user_id).filter(cls.is_deleted == 0)

        except Exception as e:
            loggings.exception(1, e)
            return {'code': RET.DBERR, 'message': '数据库异常，获取信息失败', 'error': str(e)}

        if not user_info.first():
            return {'code': RET.NODATA, 'message': '无该平台用户账号信息', 'error': '无该平台用户账号信息'}

        args = {
            "open_id": open_id,
            "head_pic": head_imgurl
        }

        try:
            user_info.update(args)
            db.session.commit()
        except Exception as e:
            db.session.rollback()
            return {'code': RET.DBERR, 'message': '数据库异常，修改信息失败', 'error': str(e)}

        return {'code': RET.OK, 'message': '绑定成功'}

    # 微信登录
    @classmethod
    def weixin_login(cls, **kwargs):
        open_id = kwargs.get('openid')

        # 搜索openid
        try:
            filter_list = [cls.open_id == open_id, cls.is_deleted == 0]
            user_info = db.session.query(cls).filter(*filter_list).first()
        except Exception as e:
            return {'code': RET.DBERR, 'message': '获取用户信息失败', 'error': str(e)}
        db.session.close()

        # 如果无数据，用户不存在
        if not user_info:
            return {'code': RET.NODATA, 'message': '该微信未绑定', 'error': '该微信未绑定'}

        user_info = commons.query_to_dict(user_info)
        user_id = user_info.get('user_id')
        login_type = user_info.get('login_type')
        user_type = user_info.get('user_type')
        user_name = user_info.get('user_name')

        # 验证成功，生成token
        token = UserTokenService.create_token(user_id, user_name, user_type)

        back_data = {
            'user_id': user_id,
            'user_name': user_name,
            'login_type': login_type,
            'role_type': user_type,
            'token': token
        }
        return {'code': RET.OK, 'message': '登录成功', 'data': back_data}

    @classmethod
    def verify_token(cls, **kwargs):
        token = kwargs.get('token')
        if not token:
            return {'code': RET.NODATA, 'message': 'token不存在', 'data': 'token不存在'}
        from manage import app
        secret_key = app.config['SECRET_KEY']
        from utils.jwt_util import JwtToken

        verify_status, payload_data = JwtToken.parse_token(token, secret_key=secret_key)
        if not verify_status:
            return {'code': RET.OK, 'message': 'token过期', 'data': {'expired': True}}
        else:
            return {'code': RET.OK, 'message': 'token有效', 'data': {'expired': False}}